package com.thinkgem.jeesite.modules.fantasy.web;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;

import com.thinkgem.jeesite.modules.fantasy.common.constant.Constants;
import com.thinkgem.jeesite.modules.fantasy.utils.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.thinkgem.jeesite.modules.fantasy.common.scheduler.RandomItems;
import com.thinkgem.jeesite.modules.fantasy.entity.CityMap;
import com.thinkgem.jeesite.modules.fantasy.entity.FantasyUserPosition;
import com.thinkgem.jeesite.modules.fantasy.entity.ItemType;
import com.thinkgem.jeesite.modules.fantasy.entity.NPCPosition;
import com.thinkgem.jeesite.modules.fantasy.service.impl.CityMapService;
import com.thinkgem.jeesite.modules.fantasy.service.impl.ItemTypeService;
import com.thinkgem.jeesite.modules.fantasy.service.impl.NPCPositionService;
import com.thinkgem.jeesite.modules.fantasy.utils.RandomUtils;

/**
* <p>Title: WorldInit</p>
* <p>Description: 初始化世界，一切一切的开始。</p>
* <p>Company: www.huanzhidadi.xin</p>
* @author wanghui
* @date 2017年12月2日
*/
@Controller
public class WorldInit {
	/**
	 * 日志对象
	 */
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	public CityMapService cityMapService;
	@Autowired
	public NPCPositionService npcPositionService;
	@Autowired
	public ItemTypeService itemTypeService;
	//static修饰的是类变量，只在类加载时实例化一次。
	//城市map，以城市id为key，城市对象为value，由initCities()方法初始化。
	public static Map<String, CityMap> cities = new HashMap<String, CityMap>();
	//NPCmap，以npc位置id为key，npc位置对象为value，由initNPCs()方法初始化。
	public static Map<String, ArrayList<NPCPosition>> npcs = new HashMap<String, ArrayList<NPCPosition>>();
	//初始化玩家位置
	public static Map<String, ArrayList<FantasyUserPosition>> users = new HashMap<String, ArrayList<FantasyUserPosition>>();
	//初始化道具类型
	public static Map<String, ItemType> itemTypes = new HashMap<String, ItemType>();
	//初始化地面上的随机道具
	public static Map<String, ItemType[]> ranItems = new HashMap<String, ItemType[]>();

	@Autowired
	private RedisUtil redisUtil;
	
	/**
	* <p>Title: init</p>
	* <p>Description: 容器启动完成时执行该方法，进行初始化</p>
	*/
	@PostConstruct
	public void init() {
		long startTime = System.currentTimeMillis();
		logger.info("世界初始化开始。");
		initCities();
		initNPCs();
		initAllItems();
		//randomItems();
		//启动时不再随机生成地面道具了，改为在定时器中生成。
		/*RandomItems ri = new RandomItems(cities, itemTypes, ranItems);
		ri.randomItem();*/
		//使用定时器发放道具，系统启动1分钟后执行，每隔5分钟执行。
		ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
		long initialDelay1 = 1;
		long period1 = 5;
		service.scheduleAtFixedRate(new RandomItems(cities, itemTypes, ranItems),
				initialDelay1, period1, TimeUnit.MINUTES);
		
		logger.info("世界初始化结束。");
		logger.info("初始化完成用时： {}秒", (System.currentTimeMillis() - startTime) / 1000f);
	}
	
	/**
	* <p>Title: initCities</p>
	* <p>Description: 城市初始化，把所有地点加载到内存map中。</p>
	*/
	public void initCities() {
		logger.info("城市初始化开始。");

		List<CityMap> cityList = cityMapService.initMaps();
		logger.info("城市大小：{}", cityList.size());
		for (CityMap cityMap : cityList) {
			cities.put(cityMap.getId(), cityMap);
			//初始化时，将cityMap所属的city保存到redis中
			redisUtil.setValue(Constants.REDIS_CITYMAP_ + cityMap.getId(), cityMap.getCityid());
		}
		logger.info("城市初始化结束。");
	}
	
	/**
	* <p>Title: initNPCs</p>
	* <p>Description: NPC初始化，从数据库中获取所有npc的位置信息，加载到内存map中。</p>
	*/
	public void initNPCs() {
		logger.info("NPC初始化开始。");
		List<NPCPosition> npcList = npcPositionService.initNPCs();
		logger.info("NPC数量：{}", npcList.size());
		for (NPCPosition npc : npcList) {
			putAdd(npc.getMapid(), npc);
		}
		logger.debug(npcs.toString());
		
		logger.info("NPC初始化结束。");
	}
	
	/**
	* <p>Title: putAdd</p>
	* <p>Description: 使用ArrayList实现一个Key对应一个ArrayList实现一对多，一个地点可以有多个npc</p>
	* @param key
	* @param npcPosition
	*/
	public static void putAdd(String key, NPCPosition npcPosition){
		if(!npcs.containsKey(key)){
			npcs.put(key, new ArrayList<NPCPosition>());
		}
		npcs.get(key).add(npcPosition);
	}
	
	/**
	* <p>Title: initAllItems</p>
	* <p>Description: 普通道具初始化，从数据库中获取所有道具类型，加载奥内存map中。</p>
	*/
	public void initAllItems() {
		logger.info("普通道具初始化开始。");

		List<ItemType> itemTypeList = itemTypeService.initCommonItems();
		logger.info("普通道具总数：{}", itemTypeList.size());
		for (ItemType itemType : itemTypeList) {
			itemTypes.put(itemType.getId(), itemType);
		}
		logger.info("普通道具初始化结束。");
	}
	
	/**
	* <p>Title: randomItems</p>
	* <p>Description: 随机发送道具到各个地点</p>
	*/
	public void randomItems() {
		logger.info("随机发送道具开始。");
		logger.debug("cities.size() = {}", cities.size());
		logger.debug("itemTypes.size() = {}", itemTypes.size());

		int count = cities.size();
		while (count > 0) {//有多少地点就初始化多少个道具
			count--;
			logger.debug("第{}次", (cities.size() - count));
			CityMap cityMap = RandomUtils.getRandomValueFromMap(cities);
			logger.debug("randCity = {}， id = {}", cityMap.getPlacename(), cityMap.getId());
			ItemType itemType = RandomUtils.getRandomValueFromMap(itemTypes);
			logger.debug("randItem = {}", itemType.getName());
			//使用数组存储数据，实现在页面的固定格子显示道具。
			if(!ranItems.containsKey(cityMap.getId())){//如果当前地点没有初始化过道具，就生成一个新的道具数组
				ranItems.put(cityMap.getId(), new ItemType[30]);
			}
			ItemType[] items = ranItems.get(cityMap.getId());//获取该地点上的道具数组
			for (int i=0; i<items.length; i++) {
				//循环该地点的道具数组，在第一个为空的格子中生成一个新的道具，跳出循环
				if (items[i] == null) {
					items[i] = itemTypes.get(itemType.getId());
					break;
				}
			}
		}
		logger.info("随机发送道具结束。");
	}
}
